package com.lry.rpc.netty.client;

import com.lry.protocol.RpcMessage;
import com.lry.rpc.netty.MsgType;
import com.lry.rpc.netty.processor.Processor;
import com.lry.rpc.netty.processor.ProcessorFactory;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import static com.lry.rpc.netty.client.ClientCache.ID_GEN;


@Slf4j
public class ClientHandler extends ChannelInboundHandlerAdapter {

    private void closeChannelHandlerContext(ChannelHandlerContext ctx) {
        if (log.isInfoEnabled()) {
            log.info("closeChannelHandlerContext channel:" + ctx.channel());
        }
        ctx.disconnect();
        ctx.close();
    }

    @Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof RpcMessage) {
            RpcMessage rpcMessage = (RpcMessage) msg;
            log.info("read:" + rpcMessage.getBody());

            Processor processor = ProcessorFactory.getProcessor(rpcMessage.getMessageType());
            processor.process(ctx.channel(),rpcMessage);
        }
        super.channelRead(ctx, msg);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("inactive:" + ctx);
        closeChannelHandlerContext(ctx);
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("channel exx:" + cause.getMessage() + ",channel:" + ctx.channel());
        }
//        closeChannelHandlerContext(ctx);
        super.exceptionCaught(ctx, cause);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            log.info("idle:" + evt);
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state() == IdleState.READER_IDLE) {
                if (log.isInfoEnabled()) {
                    log.info("channel:" + ctx.channel() + " read idle.");
                }
                try {
                    closeChannelHandlerContext(ctx);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            } else if (idleStateEvent.state() == IdleState.WRITER_IDLE) {
                //发送心跳
                RpcMessage rpcMessage = new RpcMessage(ID_GEN.getAndIncrement(), MsgType.HEARTBEAT_REQUEST.getCode(), null);
                ctx.channel().writeAndFlush(rpcMessage);
            }
        }

    }
}
